package com.qf.aop.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.qf.aop.annocation.LoginUser;
import com.qf.entity.User;
import com.qf.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class LoginUserAop {

    // 该方法就会在加了@loginUser的接口之前被调用
    @Around("@annotation(loginUser)")
    public Object parseToken(ProceedingJoinPoint point, LoginUser loginUser) throws Throwable {
        log.debug("LoginUserAop");
        // 0.先获取HttpServletRequest对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 1.获取token
        String token = request.getHeader("Authorization"); // ?需要

        if(StringUtils.isEmpty(token)){
            token = request.getParameter("token");
        }

        User user = null; // 代表当前登录的用户
        if (!StringUtils.isEmpty(token)) {

            try {
                // 2.解析token
                DecodedJWT verifier = JWTUtils.verifier(token);

                // 3.从tokne中获取用户Id
                String id = verifier.getClaim("id").asString();

                // 4.封装成一个User对象
                user = new User();
                user.setId(Integer.parseInt(id));

            } catch (Exception e) {
                log.warn("token有误", e);
            }
        }

        // 5.把user往下传递
        Object[] args = point.getArgs(); // 目标方法的参数
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof User) {
                args[i]=user;
                break;
            }
        }

        // 6.接着方法下调用
        return point.proceed(args);
    }
}
